package com.edu.networkexperimentation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.edu.networkexperimentation.common.DataUtil;
import com.edu.networkexperimentation.contant.PaperConstant;
import com.edu.networkexperimentation.mapper.*;
import com.edu.networkexperimentation.model.algorithm.FitnessUtils;
import com.edu.networkexperimentation.model.algorithm.Individual;
import com.edu.networkexperimentation.model.algorithm.PaperResult;
import com.edu.networkexperimentation.model.domain.*;
import com.edu.networkexperimentation.model.domain.Process;
import com.edu.networkexperimentation.model.request.RequestAnswer;
import com.edu.networkexperimentation.model.request.RequestPaperGenetic;
import com.edu.networkexperimentation.model.response.ResponseHistoryAnswer;
import com.edu.networkexperimentation.model.response.ResponseHistoryPaper;
import com.edu.networkexperimentation.model.response.ResponsePaper;
import com.edu.networkexperimentation.service.GeneticService;
import com.edu.networkexperimentation.service.PaperService;
import com.edu.networkexperimentation.service.RecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.FileWriter;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 29764
 * @description 针对表【paper】的数据库操作Service实现
 * @createDate 2023-06-05 20:47:20
 */
@Service
@Slf4j
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper>
        implements PaperService {

    @Resource
    private AnswerMapper answerMapper;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private GeneticService geneticService;

    @Resource
    private EffectMapper effectMapper;

    @Resource
    private ResultMapper resultMapper;

    @Resource
    private RecordService recordService;

    @Resource
    private ProcessMapper processMapper;

    /*
    @Override
    public ResponsePaper preparePaper(RequestPaperGenetic requestPaper, long flag) {
        Paper paper = new Paper();
        paper.setTitle(requestPaper.getTitle());
        paper.setUserID((long) requestPaper.getStuid());
        this.save(paper);
        ResponsePaper responsePaper = new ResponsePaper(paper);
        Individual individual = new Individual();
        int questionType = 3;


        SecureRandom secureRandom = new SecureRandom();
        String t_flag = "genetic" + System.currentTimeMillis();
        secureRandom.setSeed(t_flag.getBytes());

        int allNum = 0;
        for (int j = 0; j < questionType; j++) {
            QueryWrapper<Question> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Question::getType, j);
            List<Question> questions = questionMapper.selectList(wrapper);
            int t = questions.size();
            allNum += requestPaper.getNums()[j];
            for (int k = 0; k < requestPaper.getNums()[j]; k++) {
                int index = secureRandom.nextInt(t);
                Question question = questions.get(index);
                individual.getQuestions().add(question);
            }
        }
        double fitness = FitnessUtils.getFitness(individual, requestPaper.getDifficulty());
        individual.setFitness(fitness);
        responsePaper.setFitness(fitness);

        individual.getQuestions().forEach(item -> {
            // log.info("id:\t" + item.getId());
            Answer answer = new Answer();
            answer.setContent("");
            answer.setType(item.getType());
            answer.setPaperid(paper.getId());
            answer.setQuestionid(item.getId());
            answer.setIstrue(0);
            answerMapper.insert(answer);
//            log.info("问题种类:\t" + item.getType() + "\t" + item.getType().equals("0"));
            switch (item.getType()) {
                case "0":
                    responsePaper.addXzQuestion(item);
                    break;
                case "1":
                    responsePaper.addPdQuestion(item);
                    break;
                case "2":
                    responsePaper.addTkQuestion(item);
                    break;
            }
        });
        Effect effect = new Effect();
        effect.setPaperid(paper.getId());
        effect.setType(1);
        effect.setIterationnum(1);
        effect.setFitness(DataUtil.des(individual.getFitness()));
        effect.setQuestionnum(allNum);
        effect.setDifficulty(DataUtil.des(individual.getDifficulty()));
        effect.setKnowledgecoverage(0.0);
        effectMapper.insert(effect);
        Result result = new Result();
        result.setEffectid(effect.getId());
        result.setProcedureid(flag);
        resultMapper.insert(result);

        return responsePaper;
    }
    */
    @Override
    public ResponsePaper preparePaperAgain(RequestPaperGenetic requestPaper, long flag) {
        QueryWrapper<Record> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Record::getUserid, requestPaper.getStuid()).orderByAsc(Record::getSectionid);
        List<Record> records = recordService.list(queryWrapper);
        List<Integer> rates = new ArrayList<>();
        records.forEach(record -> {
            rates.add(record.getNum());
        });
        Paper paper = new Paper();
        paper.setTitle(requestPaper.getTitle());
        paper.setUserID((long) requestPaper.getStuid());
        this.save(paper);
        ResponsePaper responsePaper = new ResponsePaper(paper);
        List<List<Question>> questionsList = new ArrayList<>();

        int questionType = 3;

        for (int i = 0; i < questionType; i++) {
            QueryWrapper<Question> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Question::getType, i);
            List<Question> questions = questionMapper.selectList(wrapper);
            questionsList.add(questions);
        }
        SecureRandom secureRandom = new SecureRandom();
        String t_flag = "genetic" + System.currentTimeMillis();
        secureRandom.setSeed(t_flag.getBytes());

        List<Double> fitnessList = new ArrayList<>();
        double max_fitness = 0;
        Individual individual = new Individual();
        int allNum = 0;
        for (int i = 0; i < 100; i++) {
            Individual individual1 = new Individual();
            for (int j = 0; j < questionType; j++) {
                List<Question> questions = questionsList.get(j);
                int t = questions.size();
                allNum += requestPaper.getNums()[j];
                for (int k = 0; k < requestPaper.getNums()[j]; k++) {
                    int index = secureRandom.nextInt(t);
                    Question question = questions.get(index);
                    individual1.getQuestions().add(question);
                }
            }
            double fitness = FitnessUtils.getFitness(individual1, requestPaper.getDifficulty(), rates);
            individual1.setFitness(fitness);
            fitnessList.add(DataUtil.des(fitness));
            if (fitness > max_fitness) {
                individual = individual1;
                max_fitness = fitness;
            }
        }

        StringBuilder str = new StringBuilder();
        for(double item : fitnessList) {
            str.append(item).append(",");
        }

        Process process = new Process();
        process.setPaperid(paper.getId());
        process.setMaxfitness(str.toString());
        process.setType(0);
        processMapper.insert(process);
        String path1 = "D:\\projects\\IDEAProjects\\NetworkExperimentation\\r.txt";
        try (FileWriter fileWriter = new FileWriter(path1)) {
            fileWriter.append(str);
        } catch (IOException e) {
            e.printStackTrace();
        }

        individual.getQuestions().forEach(item -> {
            // log.info("id:\t" + item.getId());
            Answer answer = new Answer();
            answer.setContent("");
            answer.setType(item.getType());
            answer.setPaperid(paper.getId());
            answer.setQuestionid(item.getId());
            answer.setIstrue(0);
            answerMapper.insert(answer);
//            log.info("问题种类:\t" + item.getType() + "\t" + item.getType().equals("0"));
            switch (item.getType()) {
                case "0":
                    responsePaper.addXzQuestion(item);
                    break;
                case "1":
                    responsePaper.addPdQuestion(item);
                    break;
                case "2":
                    responsePaper.addTkQuestion(item);
                    break;
            }
        });
        responsePaper.setFitness(max_fitness);


        Effect effect = new Effect();
        effect.setPaperid(paper.getId());
        effect.setType(2);
        effect.setIterationnum(200);
        effect.setFitness(DataUtil.des(individual.getFitness()));
        effect.setQuestionnum(allNum / 100);
        effect.setDifficulty(DataUtil.des(individual.getDifficulty()));
        effect.setKnowledgecoverage(0.0);
        effectMapper.insert(effect);

        Result result = new Result();
        result.setEffectid(effect.getId());
        result.setProcedureid(flag);
        resultMapper.insert(result);
        return responsePaper;
    }


    @Override
    public ResponsePaper preparePaperByGenetic(RequestPaperGenetic requestPaperGenetic, long flag) {
        PaperResult paperResult = geneticService.get_Paper(
                requestPaperGenetic.getStuid(), requestPaperGenetic.getDifficulty(), requestPaperGenetic.getNums());

        List<Question> questions = paperResult.getQuestions();
        Paper paper = new Paper();
        paper.setTitle(requestPaperGenetic.getTitle());
        paper.setUserID((long) requestPaperGenetic.getStuid());
        this.save(paper);
        ResponsePaper responsePaper = new ResponsePaper(paper);
        questions.forEach(item -> {
            // log.info("id:\t" + item.getId());
            Answer answer = new Answer();
            answer.setContent("");
            answer.setType(item.getType());
            answer.setPaperid(paper.getId());
            answer.setQuestionid(item.getId());
            answer.setIstrue(0);
            answerMapper.insert(answer);
//            log.info("问题种类:\t" + item.getType() + "\t" + item.getType().equals("0"));
            switch (item.getType()) {
                case "0":
                    responsePaper.addXzQuestion(item);
                    break;
                case "1":
                    responsePaper.addPdQuestion(item);
                    break;
                case "2":
                    responsePaper.addTkQuestion(item);
                    break;
            }
        });
        responsePaper.setFitness(paperResult.getFitness());


        Process process = new Process();
        process.setPaperid(paper.getId());
        process.setMaxfitness(paperResult.getMaxFitness());
        process.setAveragefitness(paperResult.getAverageFitness());
        process.setType(1);
        processMapper.insert(process);

        Effect effect = new Effect();
        effect.setPaperid(paper.getId());
        effect.setType(0);
        effect.setIterationnum(paperResult.getIterationNum() + 1);
        effect.setFitness(DataUtil.des(paperResult.getFitness()));
        effect.setQuestionnum(paperResult.getQuestionNum());
        effect.setDifficulty(DataUtil.des(paperResult.getDifficulty()));
        effect.setKnowledgecoverage(paperResult.getKnowledgeCoverage());
        effectMapper.insert(effect);

        Result result = new Result();
        result.setEffectid(effect.getId());
        result.setProcedureid(flag);
        resultMapper.insert(result);
        return responsePaper;
    }

    @Override
    public ResponsePaper preparePaperByNewGenetic(RequestPaperGenetic requestPaperGenetic, long flag) {
        PaperResult paperResult = geneticService.get_new_Paper(
                requestPaperGenetic.getStuid(), requestPaperGenetic.getDifficulty(), requestPaperGenetic.getNums());

        List<Question> questions = paperResult.getQuestions();
        Paper paper = new Paper();
        paper.setTitle(requestPaperGenetic.getTitle());
        paper.setUserID((long) requestPaperGenetic.getStuid());
        this.save(paper);
        ResponsePaper responsePaper = new ResponsePaper(paper);
        questions.forEach(item -> {
            // log.info("id:\t" + item.getId());
            Answer answer = new Answer();
            answer.setContent("");
            answer.setType(item.getType());
            answer.setPaperid(paper.getId());
            answer.setQuestionid(item.getId());
            answer.setIstrue(0);
            answerMapper.insert(answer);
//            log.info("问题种类:\t" + item.getType() + "\t" + item.getType().equals("0"));
            switch (item.getType()) {
                case "0":
                    responsePaper.addXzQuestion(item);
                    break;
                case "1":
                    responsePaper.addPdQuestion(item);
                    break;
                case "2":
                    responsePaper.addTkQuestion(item);
                    break;
            }
        });
        responsePaper.setFitness(paperResult.getFitness());


        Process process = new Process();
        process.setPaperid(paper.getId());
        process.setMaxfitness(paperResult.getMaxFitness());
        process.setAveragefitness(paperResult.getAverageFitness());
        process.setType(2);
        processMapper.insert(process);

        Effect effect = new Effect();
        effect.setPaperid(paper.getId());
        effect.setType(0);
        effect.setIterationnum(paperResult.getIterationNum() + 1);
        effect.setFitness(DataUtil.des(paperResult.getFitness()));
        effect.setQuestionnum(paperResult.getQuestionNum());
        effect.setDifficulty(DataUtil.des(paperResult.getDifficulty()));
        effect.setKnowledgecoverage(paperResult.getKnowledgeCoverage());
        effectMapper.insert(effect);

        Result result = new Result();
        result.setEffectid(effect.getId());
        result.setProcedureid(flag);
        resultMapper.insert(result);
        return responsePaper;
    }

    @Override
    public void submitPaper(List<RequestAnswer> requestAnswers) {
        RequestAnswer t = requestAnswers.get(0);
        Paper paper = this.getById(t.getPaperID());
        paper.setIsAnswered(1);
        this.updateById(paper);
        requestAnswers.forEach(item -> {
            QueryWrapper<Answer> wrapper = new QueryWrapper<>();
            wrapper.eq("questionID", item.getQuestionID());
            wrapper.eq("paperID", item.getPaperID());
            Answer answer = answerMapper.selectOne(wrapper);
            if (answer != null) {
                answer.setContent(item.getContent());
                Question question = questionMapper.selectById(item.getQuestionID());
                int type = Integer.parseInt(question.getType());
                switch (type) {
                    case PaperConstant.XZ_TYPE:
                        answer.setIstrue(isTrue(answer.getContent(), question.getCorrectchoice().toString()));
                        break;
                    case PaperConstant.PD_TYPE:
                        answer.setIstrue(isTrue(answer.getContent(), question.getIstrue().toString()));
                        break;
                    case PaperConstant.TK_TYPE:
                        answer.setIstrue(isTrue(answer.getContent(), question.getCorrectcontent()));
                        break;
                }
                answerMapper.updateById(answer);
            }
        });
    }

    @Override
    public ResponseHistoryPaper getPaperByID(Long id) {
        ResponseHistoryPaper paper = new ResponseHistoryPaper(this.getById(id));
//        if (paper.getIsAnswered() == 0) return paper;
        QueryWrapper<Answer> wrapper = new QueryWrapper<>();
        wrapper.eq("paperID", paper.getId());
        List<Answer> answers = answerMapper.selectList(wrapper);
        answers.forEach(item -> {
            Question question = questionMapper.selectById(item.getQuestionid());
            int type = Integer.parseInt(question.getType());
            switch (type) {
                case PaperConstant.XZ_TYPE:
                    paper.addXzAnswer(new ResponseHistoryAnswer(question, item));
                    break;
                case PaperConstant.PD_TYPE:
                    paper.addPdAnswer(new ResponseHistoryAnswer(question, item));
                    break;
                case PaperConstant.TK_TYPE:
                    paper.addTkAnswer(new ResponseHistoryAnswer(question, item));
                    break;
            }
        });
        return paper;
    }

    @Override
    public List<ResponseHistoryPaper> getAllPaperByUserID(Long id) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.eq("userID", id);
        List<Paper> papers = this.list(wrapper);
        List<Paper> list = new ArrayList<>();
        for (int i = 2; i < papers.size(); i+=3) {
            list.add(papers.get(i));
        }
        papers = list;
        List<ResponseHistoryPaper> historyPapers = new ArrayList<>();
        papers.forEach(item -> {
            historyPapers.add(new ResponseHistoryPaper(item));
        });
        return historyPapers;
    }

    private int isTrue(String answer, String correctAnswer) {
        return correctAnswer.equals(answer) ? 1 : 0;
    }

}




